/**
 * validate i wg
 * 
 * base on jquery
 * 
 * @param $ window 
 * @author wanggang
 * @return true 验证成功 false 验证失败
 * @version 0.1
 * @constructor jQuery
 * 
 */
(function($){
	/*
	 * 所有验证的类型注册容器
	 * 用此容器的原因是：
	 * 1、因为有多个className,可能有些class定义是与此验证无关的，只是用于样式的控制，
	 *		所以当以非用于validate的class用于window.eval时会因为取不得方法而报错，同时也因此而加大了程序的运行负担
	 * 2、要运行的初始化时添加到每容器中
	 * 
	 */
	var validatePattern = ['required','less_than','int_range','validate_digits',
				'float_range','validate_alpha','validate_alphanum','validate_email',
				'validate_url','validate_currency_dollar','validate_integer',
				'validate_ip','validate_id_number','validate_chinese','validate_phone',
				'validate_mobile_phone','validate_zip','validate_qq','validate_folat','validate_forbiddenChar',
				'validate_equals','less_than_equal','less_than_node','less_than_equal_node',
				'great_than','great_than_equals','great_than_node','great_than_equals_node',
				'great_than_equals_nodeBydate','min_length','max_length','length_range','user_define','validate_folat2'];
				
	// 得到表单
	
	$.fn.extend({
		validate : function(){
			var errorList = new Array();
			var result = true;
			// 取出当前表单中的所有需要验证的项
			var validateNode = $('#'+this.attr('id')+' input[type!="button"] , #'+this.attr('id')+' select , #'+this.attr('id')+' textarea');
			$.each(validateNode , function(){
				$(this).removeClass('i_validate_object');
			});
			// 对每一个节点进行操作
			$.each(validateNode , function(){
				// 取得节点的class
//				var _className = validate.util.getClassName($(this));
				var _className = validate.util.splitClassName($(this));
//				var _title = $(this).attr('title');
				var _value = $(this).val();
				var _id = $(this).attr('id');
				/*
				 * 按className来取出验证信息
				 * 返回信息为{
				 * 	regex : RegExp || Function
				 * 	title : message || 可能替换信息的message
				 * }
				 * 
				 * 调用方式为window.eval('required'); || window.eval('required(this)');
				 * 
				 * 验证的类型有两种一种是正则的方式 一种是function的方式
				 */
				 if(null != _className && _className.length > 0){
				 	// alert(_className);
				 	for(var i=0;i<_className.length;i++){
				 		/*
				 		 * 修改于2010-05-22 
				 		 * 修改原因: 当有多个验证项时，那么永远得到的都是第一个验证项的提示信息
				 		 */
				 		var _title = $(this).attr('title');
				 		// 此处的className就是以空格分割之后的ClassName
				 		var validateClass = validate.util.getClassName(_className[i]);
				 		// 查看此className是否是用于validate,如果不是就跳过此次循环
				 		var isValidate = validate.util.inArray(validateClass.realClass , validatePattern);
				 		// 如果不是验证中的class就返回
				 		if(isValidate){
				 			// 如果在错误的列表中已存在此节点就不再进行验证了，跳出此次循环
				 			var validated = validate.util.inArray($(this) , errorList);
				 			if(validated){
				 				continue;
				 			}
							// 取出validate的提示信息
							var _defaultTitle = window.eval('$.validateRule.'+validateClass.realClass+'.title');
							var validateType = window.eval('$.validateRule.'+validateClass.realClass+'.regex');
							// 判断用户自定义的提示信息是否存在,,如果信息不存在
							if(null == _title || _title == ''){
								// 如果用户自定义的title为空 , 那就去取用系统默认的方法
								/**
								 * @param _defaultTitle 系统默认的title信息
								 * @param validateClass.range 在类中得到数组值
								 * 
								 * @return 通过替换%s来产生最新的信息
								 * 
								 */
								_title = validate.util.createValidateMsg(_defaultTitle , validateClass.range);
							}
							// 如果用正则表达式进行验证
							if(validateType.constructor == RegExp){
								// alert("validateType >> "+validateType);
								// 取出element的值 , 并进行验证
								var _result = validateType.test(_value);
								// 如果有一次验证错误那就返回一个false，但是不停止验证
								if(result && !_result){
									result = false;
								}
								/*
								 * 处理验证信息
								 * _title , elem
								 */
								validate.util.manageValidateMsg(_title , $(this) , _result);
								if(!_result){
									errorList.push($(this));
								}
								// 验证之后的信息debug
								$('#msg').text($('#msg').text() + '总体结果: ' + result + '此次验证对象为['+$(this).attr('name')+'],当前验证结果为:'+_result+'\n');
							}
							
							// 如果是以function进行验证的
							if(validateType.constructor == Function){
								var tt = validateType(_title , $(this) , _className[i]);
								// 如果有一次验证错误那就返回一个false，但是不停止验证
								if(result && !tt){
									result = false;
								}
								validate.util.manageValidateMsg(_title , $(this) , tt);
								if(!tt){
									errorList.push($(this));
								}
								// 验证之后的信息debug
//								$('#msg').text($('#msg').text() + '总体结果: ' + result + '此次验证对象为['+$(this).attr('name')+'],当前验证结果为:'+tt+'\n');
							}
				 		}
				 	}
				 }
				 
			});
			if(errorList.length > 0){
				$(errorList[0]).select();
			}
			return result;
		}
	});
	/**
	 * 建立一个工具类
	 */
	 var validate = {};
	 validate.util = {
	 	
	 	getXY : function(event){
		    var ev = event || window.event;
		 	if(ev.pageX || ev.pageY)
		 	{
		 		return {x:ev.pageX , y:ev.pageY};
		 	}else
		 	{
		 		return {
		 			x:ev.clientX + document.body.scrollLeft - document.body.clientLeft , 
		 			y:ev.clientY + document.body.scrollTop - document.body.clientTop
		 		};
		 	}
		},
	 	
	 	getY : function(e){
		    e = e || window.event;
		 	return e.pageY || e.clientY+document.body.scrollTop;			
		},
	 	/**
	 	 * 通过替换%s来生成一个新的title信息
	 	 * @param defautlTitle 系统默认的提示信息
	 	 * @param range 是一个数组里面有要替换的数字
	 	 * 
	 	 * @return 返回替换之后的信息
	 	 *  
	 	 */
	 	createValidateMsg : function(defautlTitle , range){
	 		var result = '';
	 		if(null == range){
	 			/*
	 			 * 修改于2010-05-22 
	 			 * 修改原因：如果没有设置class的range就取不到默认的信息
	 			 */
	 			result = defautlTitle;
	 		}else{
	 			for(var i=0;i<range.length;i++){
	 				// 从range[]中的信息提示
	 				if( null != $( '#'+range[i] ) ){
	 					if( typeof( $( '#'+range[i] ).val() )!='undefined' ){
		 					defautlTitle = defautlTitle.replace('%s' , $( '#'+range[i] ).val() );
	 					}else{
	 						defautlTitle = defautlTitle.replace('%s' , range[i]);
	 					}
	 				}else{
		 				defautlTitle = defautlTitle.replace('%s' , range[i]);
	 				}
	 			}
	 			result = defautlTitle;
	 		}
	 		return result;
	 	},
	 	
	 	/**
	 	 * @param val 值
	 	 * @param array 判断是否包含的数组
	 	 * 
	 	 * 判断某一个元素是否在一个数组当中
	 	 */
	 	inArray : function(val , array){
	 		var result = false;
	 		if(val==null || array == null){
	 			result = false;
	 		}
	 		for(var i=0;i<array.length;i++){
	 			if(val.constructor == Object && array[i].constructor == Object){
	 				if($(val).attr('type')==$(array[i]).attr('type') 
	 						&& $(val).attr('class') == $(array[i]).attr('class') 
	 						&& $(val).attr('title') == $(array[i]).attr('title') 
	 						&& $(val).attr('name') == $(array[i]).attr('name') 
	 						&& $(val).attr('id') == $(array[i]).attr('id') 
	 						&& $(val).attr('value') == $(array[i]).attr('value') ){
	 					result = true;
	 					break;
	 				}
	 			}else{
		 			if(val == array[i]){
		 				result = true;
		 				break;
		 			}
	 			}
	 		}
	 		return result;
	 	},
	 	
	 	/**
	 	 * class的样式为less_than:0-10;
	 	 * 取出真实的className
	 	 * 返回的值为 {
	 	 * 	realClass : 'className'
	 	 * 	range : 如果没有就为null ， 如果有就以'-'进行分割得到一个数组，此数组可能为一个元素也可能为多个元素
	 	 * }
	 	 * 
	 	 * 
	 	 */
	 	getClassName : function(_class){
	 		// 取出className
	 		// var _class = $(elem).attr('class');
	 		var arr = _class.split(':');
	 		if(arr.length < 2){
	 			return {
	 				realClass : arr[0],
	 				range : null
	 			};
	 		}else if(arr.length = 2){
	 			return {
	 				realClass : arr[0],
	 				range : arr[1].split('-')
	 			};
	 		}
	 	},
	 	/**
	 	 * 2010-04-27 13.22分添加：
	 	 * 添加原因为:
	 	 * 1、用户可以定义多个className以空格进行分割的，然后每个className以前期指定的方式进行定义
	 	 * 
	 	 */
	 	splitClassName : function(elem){
	 		var _class = $(elem).attr('class');
	 		return _class.split(' ');
	 	},
	 	/**
	 	 * 进行身份证验证时的日期验证
	 	 */
	 	 isDate : function(v,dateFormat) {
			var MONTH = "MM";
		   	var DAY = "dd";
		   	var YEAR = "yyyy";
			var regex = '^'+dateFormat.replace(YEAR,'\\d{4}').replace(MONTH,'\\d{2}').replace(DAY,'\\d{2}')+'$';
			if(!new RegExp(regex).test(v)) return false;
	
			var year = v.substr(dateFormat.indexOf(YEAR),4);
			var month = v.substr(dateFormat.indexOf(MONTH),2);
			var day = v.substr(dateFormat.indexOf(DAY),2);
			
			var d = new Date(validate.util.format('%s/%s/%s',[year,month,day]));
			return ( parseInt(month, 10) == (1+d.getMonth()) ) && 
						(parseInt(day, 10) == d.getDate()) && 
						(parseInt(year, 10) == d.getFullYear() );		
		},
		/**
		 * 格式化
		 */
	 	format : function(str,args) {
			args = args || [];
			var result = str
			for (var i = 0; i < args.length; i++){
				result = result.replace(/%s/, args[i]);	
			}
			return result;
		},
	 	/**
	 	 * 处理验证之后的信息
	 	 * @param _title 提示信息
	 	 * @param elem 被验证的对象
	 	 * 
	 	 */
	 	manageValidateMsg : function(_title , elem , result/* , promptMethod*/){
	 		/*
	 		 * 1、把被验证的对象的css添加一个新的css
	 		 * 2、生成一个提示对象，此提示对象在elem的mouseover上add , 在mouseout的事件上remove
	 		 */
	 		var tooltips = null;
	 		if(!result){
	 			tooltips = new aeroui.tooltips( elem , _title );
	 		}else{
//	 			$( elem ).removeClass( 'aeroui_tooltips_host' );
//	 			$( elem ).unbind();
				if( typeof( elem[0].release )!='undefined' && null != elem[0].release ){
					elem[0].release();
				}
	 		}	 		
	 	}
	 	
	 };
	/**
	 * @return {
	 * 	regex : RegExp  || Function
	 * 	title : message || 可能替换信息的message
	 * }
	 */
	$.validateRule = {
		// 不可缺少
		required : {
			/*
			 * 正则表达式
			 */
			regex : function(_title , elem , _class){
				if(null != $(elem).val() && $(elem).val().length > 0){
					return true;
				}else{
					return false;
				}
				
			},
			/*
			 * 提示信息
			 */
			title : '不能为空'
		},
		// 小于某数字
		less_than : {
			/*
			 * 验证的function(elem)
			 * 当前值要小于某一个值
			 * @param _title 已处理过了的title信息
			 * @param elem 被验证的对象
			 */
			regex : function(_title , elem , _class){
				// 取得当前的elem的value
				var _val = $(elem).val();
				// 得到解析之后的className
				var _className = validate.util.getClassName(_class);
				var _realClass = _className.realClass;
				var _datas = _className.range;
				var result = true;
				if(null != _datas && _datas.length > 0){
					var a = parseInt(_val);
					if(isNaN(a)){
						result = false;
					}else{
						var b = parseInt(_datas[0]);
						if(a > b){
							result = false;
						}
					}
				}
				return result;
			},
			title : '必须小于 %s '
		},
		// 整数的范围
		int_range : {
			regex : function(_title , elem , _class){
				// 取出elem的值
				var _val = $(elem).val();
				// 得到解析之后的className
				var _className = validate.util.getClassName(_class);
				var _realClass = _className.realClass;
				var _datas = _className.range;
				var result = true;
				if(null != _datas && _datas.length > 0){
					var a = parseInt(_val);
					if(isNaN(a)){
						result = false;
					}{
						var b = parseInt(_datas[0]);
						var c = parseInt(_datas[1]);
						if(a < b || a > c){
							result = false;
						}
					}
				}
				return result; 
			},
			title : '必须大于 %s 小于 %s'
		},
		// 只能是数字
		validate_digits : {
			regex : /^[\d]+$/,
			title : '只能是数字'
		},
		// 浮点数的范围
		float_range : {
			regex : function(_title , elem ,_class){
				var _val = $(elem).val();
				var _className = validate.util.getClassName(_class);
				var _realClass = _className.realClass;
				var _datas = _className.range;
				var result = true;
				if(null != _datas && _datas.length > 0){
					var a = parseFloat(_val);
					if(isNaN(a)){
						result = false;
					}{
						var b = parseFloat(_datas[0]);
						var c = parseFloat(_datas[1]);
						if(a < b || a > c){
							result = false;
						}
					}
				}
				return result; 
			},
			title : '必须大于 %s 小于 %s'
		},
		// 只能是字母
		validate_alpha : {
			regex : /^[a-zA-Z]+$/,
			title : '只能是字母'
		},
		// 只能是数字或字母
		validate_alphanum : {
			regex : /^[a-zA-Z0-9]+$/,
			title : '只能是数字或字母'
		},
		// 请输入正确的email
		validate_email : {
			regex : /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/,
			title : '请输入正确的email'
		},
		// 请输入正确的URL
		validate_url : {
			regex : /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i,
			title : '请输入正确的URL'
		},
		// 请正解的输入金额
		validate_currency_dollar : {
			regex : /^\[$￥]?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/,
			title : '请正解的输入金额'
		},
		// 请正确输入整数,可以是正负数
		validate_integer : {
			regex : /^[-+]?[1-9]\d*$|^0$/,
			title : '请正确输入整数,可以是正负数'
		},
		// 请正解输入ip
		validate_ip : {
			regex : /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
			title : '请正解输入ip'
		},
		// 请输入正解的身份证号码
		validate_id_number : {
			regex : function(_title , elem , _class){
				var v = $(elem).val();
				if(!(/^\d{17}(\d|x)$/i.test(v) || /^\d{15}$/i.test(v))) return false;
				var provinceCode = parseInt(v.substr(0,2));
				if((provinceCode < 11) || (provinceCode > 91)) return false;
				var forTestDate = v.length == 18 ? v : v.substr(0,6)+"19"+v.substr(6,15);
				var birthday = forTestDate.substr(6,8);
				if(!validate.util.isDate(birthday,'yyyyMMdd')) return false;
				if(v.length == 18) {
					v = v.replace(/x$/i,"a");
					var verifyCode = 0;
					for(var i = 17;i >= 0;i--)   
		            	verifyCode += (Math.pow(2,i) % 11) * parseInt(v.charAt(17 - i),11);
		            if(verifyCode % 11 != 1) return false;
				}
				return true;
			},
			title : '请输入正确的身份证号码'
		},
		// 只能输入汉字
		validate_chinese : {
			regex : /^[\u4e00-\u9fa5]+$/,
			title : '只能输入汉字'
		},
		// 请正解输入电话号码
		validate_phone : {
			regex : /^((0[1-9]{3})?(0[12][0-9])?[-])?\d{6,8}$/,
			title : '请正解输入电话号码'
		},
		// 请正确输入手机号 
		validate_mobile_phone : {
			regex : /(^0?[1][358][0-9]{9}$)/,
			title : '请正确输入手机号'
		},
		// 正确输入邮政编码
		validate_zip : {
			regex : /^[1-9]\d{5}$/,
			title : '正确输入邮政编码'
		},
		// 请正确输入QQ号
		validate_qq : {
			regex : /^[1-9]\d{4,8}$/,
			title : '请正确输入QQ号'
		},
		// 请正确输入浮点数
		validate_folat : {
			regex : /^[-\+]?\d+(\.\d+)?$/,
			title : '请正确录入数值型内容'
		},
		// 请正确输入正浮点数
		validate_folat2 : {
			regex : /^\d+(\.\d+)?$/,
			title : '请正确录入数值型内容'
		},
		
		// 包含非法字符
		validate_forbiddenChar : {
		regex : /^[^`~!@$%^&+=|\\\][\]\{\}:;'\,<>?]*$/,
		title : '包含非法字符'
		},
		// 请检查是否与指定项相等 className:otherNodeId
		validate_equals : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				// var _class = $(elem).attr('class');
				var result = true;
				if(_class.indexOf(':')!=-1){
					var corr_id = _class.split(":")[1];
					var corr_val = $('#'+corr_id).val();
					if(corr_val !== _val){
						result = false;
					}else{
						result = true;
					}
				}else{
					result = false;
				}
				return result;
			},
			title : '请检查是否与 %s 相等'
		},
		// 小于等于数字
		less_than_equal : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				var _className = validate.util.getClassName(_class);
				var _realClass = _className.realClass;
				var _datas = _className.range;
				var result = true;
				if(null != _datas && _datas.length > 0){
					var a = parseFloat(_val);
					if(isNaN(a)){
						result = false;
					}{
						var b = parseFloat(_datas[0]);
						if(a > b){
							result = false;
						}
					}
				}
				return result; 
			},
			title : '必须小于等于 %s '
		},
		// 只能小于某节点的值 className：nodeId
		less_than_node : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				// var _class = $(elem).attr('class');
				var result = true;
				if(_class.indexOf(':')!=-1){
					var corr_val = $('#'+_class.split(':')[1]).val();
					var a = parseFloat(corr_val);
					var b = parseFloat(_val);
					if(b < a){
						result = true;
					}else{
						result = false;
					}
				}else{
					result = false;
				}
				return result;
			},
			title : '必须小于 %s '
		},
		// 只小于等于某节点的值
		less_than_equal_node : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				// var _class = $(elem).attr('class');
				var result = true;
				if(_class.indexOf(':')!=-1){
					var corr_val = $('#'+_class.split(':')[1]).val();
					var a = parseFloat(corr_val);
					var b = parseFloat(_val);
					if(b <= a){
						result = true;
					}else{
						result = false;
					}
				}else{
					result = false;
				}
				return result;
			},
			title : '必须小于等于 %s '
		},
		// 只能大于某值
		great_than : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				var _className = validate.util.getClassName(_class);
				var _realClass = _className.realClass;
				var _datas = _className.range;
				var result = true;
				if(null != _datas && _datas.length > 0){
					var a = parseFloat(_val);
					if(isNaN(a)){
						result = false;
					}{
						var b = parseFloat(_datas[0]);
						if(a > b){
							result = true;
						}else{
							result = false;
						}
					}
				}
				return result; 
			},
			title : '必须大于 %s '
		},
		// 只能大于等于某值
		great_than_equals : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				var _className = validate.util.getClassName(_class);
				var _realClass = _className.realClass;
				var _datas = _className.range;
				var result = true;
				if(null != _datas && _datas.length > 0){
					var a = parseFloat(_val);
					if(isNaN(a)){
						result = false;
					}{
						var b = parseFloat(_datas[0]);
						if(a >= b){
							result = true;
						}else{
							result = false;
						}
					}
				}
				return result; 
			},
			title : '必须大于等于 %s '
		},
		// 只能大于某节点的值 className:nodeId
		great_than_node : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				// var _class = $(elem).attr('class');
				var result = true;
				if(_class.indexOf(':')!=-1){
					var corr_val = $('#'+_class.split(':')[1]).val();
					var a = parseFloat(corr_val);
					var b = parseFloat(_val);
					if(b > a){
						result = true;
					}else{
						result = false;
					}
				}else{
					result = false;
				}
				return result;
			},
			title : '必须大于 %s '
		},
		// 只能大于等于某节点的值 className:nodeId
		great_than_equals_node : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				// var _class = $(elem).attr('class');
				var result = true;
				if(_class.indexOf(':')!=-1){
					var corr_val = $('#'+_class.split(':')[1]).val();
					var a = new Number(corr_val);
					var b = new Number(_val);
					if(b >= a){
						result = true;
					}else{
						result = false;
					}
				}else{
					result = false;
				}
				return result;
			},
			title : '必须大于等于 %s '
		},
		// 只能大于等于某节点的值 className:nodeId
		great_than_equals_nodeBydate : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				var result = true;
				if(_class.indexOf(':')!=-1){
					var corr_val = $('#'+_class.split(':')[1]).val();
					var a = new Number(corr_val.replaceAll("-",""));
					var b = new Number(_val.replaceAll("-",""));
					if(b >= a){
						result = true;
					}else{
						result = false;
					}
				}else{
					result = false;
				}
				return result;
			},
			title : '结束时间不得早于开始时间'
		},
		// 最小长度为 calssName:10
		min_length : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				var _length = _class.split(':')[1];
				var result = true;
				if(_val == null){
					result = false;
				}else{
					if(_val.length >= parseInt(_length)){
						result = true;
					}else{
						result = false;
					}
				}
				return result;
			},
			title : '最小长度为 %s '
		},
		// 最大长度为 className:10
		max_length : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				var _length = _class.split(':')[1];
				var result = true;
				if(_val == null){
					result = false;
				}else{
					if(_val.length <= parseInt(_length)){
						result = true;
					}else{
						result = false;
					}
				}
				return result;
			},
			title : '最大长度为 %s '
		},
		// 长度范围为className:10-20
		length_range : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				var _className = validate.util.getClassName(_class);
				var _realClass = _className.realClass;
				var _datas = _className.range;
				var result = true;
				if(null != _datas && _datas.length > 0){
					var a = parseInt(_datas[0]);
					var b = parseInt(_datas[1]);
					if(_val == null){
						result = false;
					}else{
						if(_val.length >= a && _val.length <=b){
							result = true;
						}else{
							result = false;
						}
					}
				}else{
					result = false;
				}
				return result;
			},
			title : '长度大于 %s 小于 %s '
		},
		// 与自定义的样式不符className:RegExp
		user_define : {
			regex : function(_title , elem , _class){
				var _val = $(elem).val();
				var _regex = window.eval(_class.split(':')[1]);
				var result = true;
				if(_regex.constructor != RegExp){
					result = false;
				}
				if(!_regex.test(_val)){
					result = false;
				}else{
					result = true;
				}
				return result;
			},
			title : '与自定义的样式 %s 不符'
		}

	};
})(jQuery);